//noinspection
package grame

import org.apache.shiro.SecurityUtils
import org.apache.shiro.authc.UsernamePasswordToken

/**
 * @author "Shining Wang<shiningwang@topca.com>"
 */
class SecurityFilters {
    def filters = {
        all(uri: "/**") {
            before = {
                log.trace("[Filter:shiro]request:${request.forwardURI}, namespace:$controllerNamespace, controller:$controllerName, action:$actionName")

                // Ignore direct views (e.g. the default main index page).
                if (!controllerName) return true

                def subject = SecurityUtils.subject
                if (subject.principal == null) {
                    def authToken = new UsernamePasswordToken(SystemUserName.Anonymous.name(), SystemUserName.Anonymous.password.toCharArray())
                    subject.login(authToken)
                }
                // Access control by convention.
                return accessControl() {
                    permission(ControllerPermission.toPermission(controllerNamespace, controllerName, actionName ?: 'index'))
                }
            }
        }
    }

    @SuppressWarnings("GroovyUnusedDeclaration")
    // "User is not authenticated, so deal with it.",Apache Shiro Integration for Grails said.
    def onNotAuthenticated(subject, filter) {
        redirectLogin(subject, filter)
    }

    @SuppressWarnings("GroovyUnusedDeclaration")
    // "User does not have the required permission(s)",Apache Shiro Integration for Grails said.
    def onUnauthorized(subject, filter) {
        redirectLogin(subject, filter)
    }

    def redirectLogin(subject, filter) {
        def request = filter.request
        //noinspection GroovyAssignabilityCheck
        def targetUri = new StringBuilder(request.forwardURI[request.contextPath.size()..-1])
        def query = request.queryString
        if (query) {
            if (!query.startsWith('?')) {
                targetUri << '?'
            }
            targetUri << query
        }
        filter.redirect(controller: "auth", action: "login", params: [targetUri: targetUri.toString()])
    }
}
